package com.xhb.ui.proxy;

import com.teamdev.jxbrowser.net.proxy.CustomProxyConfig;
import com.teamdev.jxbrowser.net.proxy.SystemProxyConfig;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import com.xhb.biz.po.ProxyPO;
import com.xhb.biz.po.UrlPO;
import com.xhb.biz.service.ProxyService;
import com.xhb.biz.service.UrlService;
import lombok.Data;
import org.noear.solon.Solon;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 代理管理器
 * 1、用来自动加速白名单内的网站
 * 2、用来自动代理企业应用
 */
@Data
public class ProxyManager {


    private static Map<String, String> urlProxySettMap = new ConcurrentHashMap<>();

    static {
        //urlProxySettMap.put("www.google.com", "1");
        //urlProxySettMap.put("www.google.com.hk", "1");
    }

    private static Map<String, ProxyPO> proxyIdMap = new ConcurrentHashMap<>();

    /**
     * 当前代理节点的id
     */
    private String proxyId;

    private static boolean isProxy;


    public void autoProxy(String url, BrowserView browserView) {
        if (url == null) {
            return;
        }
        url = getBaseUrl(url);
        if (url == null) {
            return;
        }
        //匹配到的 代理节点的id
        String mateProxyId = mateProxyId(url);
        //不是同一个代理在去操作
        if (mateProxyId != null && !mateProxyId.equals(proxyId)) {
            String proxyRules = getProxyRules(mateProxyId);
            String exceptions = "<local>";  // bypass proxy server for local web pages
            browserView.getBrowser().profile().proxy()
                    .config(CustomProxyConfig.newInstance(proxyRules, exceptions));
            proxyId = mateProxyId;
            this.isProxy = true;
        } else if (mateProxyId==null && isProxy) {//如果不包含而且
            browserView.getBrowser().profile().proxy().config(SystemProxyConfig.newInstance());
            this.isProxy = false;
            proxyId = null;
        }
    }

    /**
     * 匹配代理节点的id
     *
     * @param url
     */
    private String mateProxyId(String url) {
        String subUrl = url;
        int count = url.split("\\.").length - 1;
        //超过2层域，去掉主机名
        if (count >= 2) {
            subUrl = url.substring(url.indexOf(".") + 1);
        }
        String mateProxyId = null;
        for (String sourceUrl : urlProxySettMap.keySet()) {
            //包含返回代理Id
            if (sourceUrl.contains(subUrl)) {
                return urlProxySettMap.get(sourceUrl);
            }
        }
        return mateProxyId;
    }

    /**
     * 获取代理
     *
     * @return
     */
    private String getProxyRules(String proxyId) {
        if (null != proxyId && proxyIdMap.containsKey(proxyId)) {
            ProxyPO proxyPO = proxyIdMap.get(proxyId);
            String proxyIP = proxyPO.getIp() + ":" + proxyPO.getPort();
            String proxyRules = "http=" + proxyIP + ";https=" + proxyIP + ";ftp=" + proxyIP + ";socks=" + proxyIP;
            return proxyRules;
        }
        return "";
    }

    /**
     * 获取基础url
     *
     * @param url
     * @return
     */
    private static String getBaseUrl(String url) {
        URI effectiveURI = null;
        try {
            URI uri = URI.create(url);
            effectiveURI = new URI(uri.getScheme(),
                    uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
        } catch (Throwable var4) {
            return null;
        }

        return effectiveURI.toString().replace("http://", "").replace("https://", "");
    }

    /**
     * 加载刷新代理配置
     */
    public static void loadSettings() {
        System.out.println("加载刷新代理配置");
        List<ProxyPO> proxyList = new ArrayList<>();
        Solon.context().getBeanAsync(ProxyService.class, bean -> {
            proxyList.addAll(bean.getProxyList());
        });
        for (ProxyPO proxyPO : proxyList) {
            proxyIdMap.put(proxyPO.getId(), proxyPO);
        }

        List<UrlPO> urlList = new ArrayList<>();
        Solon.context().getBeanAsync(UrlService.class, bean -> {
            urlList.addAll(bean.getUrlList());
        });
        for (UrlPO urlPO : urlList) {
            urlProxySettMap.put(urlPO.getUrl(), urlPO.getProxyId());
        }
    }

}
